package m

import (
	"GameServer/Common/utils"
	"fmt"
	"strconv"
	"strings"

	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"

	"GameServer/Common/data"
	"GameServer/Game/cache"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
)

type ShopItem struct {
	Tid  int64 `bson:"tid" json:"tid"`
	Num  int64 `bson:"num" json:"num"`
	Time int64 `bson:"time" json:"time"`
	Typ  int64 `bson:"typ" json:"typ"`
}

type ShopItems struct {
	BaseM
	Uid   bson.ObjectId       `bson:"_id" json:"uid"`
	Items map[int64]*ShopItem `bson:"items" json:"items"`
}

func NewShopItems() cache.EntryI {
	return &ShopItems{Items: make(map[int64]*ShopItem, 0)}
}

// 保存信息
func (s *ShopItems) Save() (err error) {
	if s.Items == nil || len(s.Items) == 0 {
		return
	}
	err = dbmodule.MgoDB.GameDB.Upsert("shopItems", bson.M{"_id": s.Uid}, s)
	if err != nil {
		return
	}
	return
}

func (s *ShopItems) Load(key interface{}) (err error) {
	switch key.(type) {
	case string:
		if key.(string) == "" {
			return errors.New("无效的key load, key empty")
		}
		s.Uid = bson.ObjectIdHex(key.(string))
	case bson.ObjectId:
		s.Uid = key.(bson.ObjectId)
	default:
		log.WithFields(log.Fields{
			"method": "ShopItems_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return s.LoadData()
}

// 加载数据
func (s *ShopItems) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("shopItems", bson.M{"_id": s.Uid}, nil, &s)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return
	}
	if s.Items == nil {
		s.Items = make(map[int64]*ShopItem, 0)
	}
	return
}

// 更新数据
func (s *ShopItems) Update(val *ShopItems) {
	Cache.Put("shopItems", s.Uid.Hex(), val)
	val.UpdateData()
}

func (u *User) GetShopItems() (r *ShopItems) {
	v, _ := Cache.Get("shopItems", u.Uid.Hex())
	r = v.(*ShopItems)
	return
}

func (s *ShopItems) CanBuyNum(typ int64, id int64) (rnum int64, err error) {
	shopItemT, err := GetShopItemT(typ, id)
	if err != nil {
		return
	}
	v, ok := s.Items[id]
	if !ok {
		v = &ShopItem{}
	}
	rnum = -1 // 表示不限制
	switch shopItemT.Limit.Condition {
	case "":
		return
	case "everyDay":
		now := utils.TNow().Unix()
		if !utils.IsSameDay(v.Time, now) {
			rnum = int64(shopItemT.Limit.Num)
			return
		}
		rnum = int64(shopItemT.Limit.Num) - v.Num
		return
	case "global":
		rnum = int64(shopItemT.Limit.Num) - v.Num
		return
	default:
		if strings.HasPrefix(shopItemT.Limit.Condition, "timeMonthDay") {
			lines := strings.Split(shopItemT.Limit.Condition, "@")
			lines1 := strings.Split(lines[1], "-")
			month, _ := strconv.ParseInt(lines1[0], 10, 64)
			day, _ := strconv.ParseInt(lines1[1], 10, 64)
			_, m1, d1 := utils.TNow().Date()
			if month == int64(m1) && int64(d1) == day {
				rnum = int64(shopItemT.Limit.Num) - v.Num
				return
			}
			return
		}
	}
	return
}

func (s *ShopItems) AddItem(typ int64, tid int64, num int64) (firstRes []data.IdKV, rItem *ShopItem, err error) {
	canNum, err := s.CanBuyNum(typ, tid)
	if err != nil {
		return
	}
	if canNum == 0 || canNum > num {
		err = errors.NewErrcode(data.Errcode.ServerErr, fmt.Sprintf("可购买数量不足canNum:%d, num:%d", canNum, num))
		return
	}
	defer s.Update(s)
	if v, ok := s.Items[tid]; ok {
		v.Num += num
		v.Time = utils.TNow().Unix()
		rItem = v
		return
	}
	st, err := GetShopItemT(typ, tid)
	firstRes = st.FirstRes
	rItem = &ShopItem{Tid: tid, Typ: typ, Num: num, Time: utils.TNow().Unix()}
	s.Items[tid] = rItem
	return
}

func GetShopItemT(typ int64, tid int64) (r data.ShopItem, err error) {
	tpl, ok := data.Get("ShopTypes", uint64(typ))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到ShopTypes商品类型配置表typ:%d", typ))
		return
	}
	styp := tpl.(data.ShopType)
	tpl1, ok := data.Get(styp.Table, uint64(tid))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有找到%s%s配置表id:%d", styp.Table, styp.Desc, tid))
		return
	}
	r = tpl1.(data.ShopItem)
	return
}
